
/**
 * Custom extensions to Ext.data.Record.  These methods are added to new Ext.data.Record objects
 * when you subclass ExtMVC.Model.
 * For example
 * model = new ExtMVC.Spec.FakeUser({
 *   id:   100,
 *   name: 'Ed'
 * });
 * alert(model.namespacedUrl('my_url')); // => '/admin/my_url.ext_json'
 */
ExtMVC.Model.RecordExtensions = {
	/**
	 * Adds logic on top of Ext.data.Record
	 */
	init		: function(config) {
		Ext.applyIf(config, {
			// set up the various variations on the model name
			className			: ExtMVC.Model.classifyName(config.modelName),
			controllerName		: ExtMVC.Model.controllerName(config.modelName),
			foreignKeyName		: ExtMVC.Model.foreignKeyName(config.modelName),

			humanPluralName		: ExtMVC.Model
					.pluralizeHumanName(config.modelName),
			humanSingularName	: ExtMVC.Model
					.singularizeHumanName(config.modelName),

			underscoreName		: config.modelName
		}
		);

		// add the data adapter, initialize it
		var adapter = ExtMVC.Model.AdapterManager.find(config.adapter
				|| ExtMVC.Model.prototype.adapter);
		if (adapter) {
			Ext.apply(config, adapter.instanceMethods);
			adapter.initialize(this);
		}

		// mix in validations package
		Ext.apply(config, ExtMVC.Model.ValidationExtensions);
		config.initializeValidationExtensions();

		Ext.apply(this, config);
	},

	/**
	 * Calculates a nested url for this object based on it's data.id and parent model
	 * @return {String} The url for this model object
	 */
	url			: function() {
		var el = this.data.id ? this : this.constructor;
		if (this.parent && this.parent.lastFetched) {
			return ExtMVC.UrlBuilder.urlFor(this.parent.get({}, -1), el);
		} else {
			return ExtMVC.UrlBuilder.urlFor(el);
		};
	},

	/**
	 * Mass-assigns field values.  Operation is wrapped in beginEdit and endEdit
	 * e.g. setValues({first_name: 'Ed', last_name: 'Spencer'})
	 * is the same as set('first_name', 'Ed'); set('last_name': 'Spencer')
	 * @param {Object} values An object containing key: value pairs for fields on this object
	 */
	setValues	: function(values) {
		this.beginEdit();
		for (var key in values) {
			this.set(key, values[key]);
		}
		this.endEdit();
	},

	/**
	 * Reads errors from a generic object and adds them to this model's internal errors object.
	 * Intended to be used mainly to process server responses
	 */
	readErrors	: function(errorsObject) {
		this.errors.readServerErrors(errorsObject);
	}
};